
#include <stdio.h>
#include <string.h>
#include "appload.h"
#include "sysdef.h"
#include "device.h"
#include "flash.h"

#define FLASH_TEST_ONCHIP 0
#define FLASH_TEST_W25QXX 1

#define FLASH_TEST FLASH_TEST_ONCHIP

#define BUF_LEN 5000

#if FLASH_TEST == FLASH_TEST_ONCHIP

#if !CONFIG_FLASH_ONCHIP
#error flash onchip is not configured
#endif
extern char __flash_user_start[];
static uint32_t flash_test_start_addr = (uint32_t)__flash_user_start;

#elif FLASH_TEST == FLASH_TEST_W25QXX

#if !CONFIG_FLASH_W25QXX
#error flash w25qxx is not configured
#endif
static uint32_t flash_test_start_addr = 0x00000000;

#else

#error flash test configured error

#endif

void flash_test(void *argv) {
    UNUSED(argv);

#if FLASH_TEST == FLASH_TEST_ONCHIP
    flash_t *flash = flash_find_by_type(FLASH_TYPE_ONCHIP);
#elif FLASH_TEST == FLASH_TEST_W25QXX
    flash_t *flash = flash_find_by_type(FLASH_TYPE_W25QXX);
#endif
    if(!flash) {
        printf("error: flash not found\n");
        return;
    }

#if FLASH_TEST == FLASH_TEST_ONCHIP
    if(flash->open(NULL)) {
#elif FLASH_TEST == FLASH_TEST_W25QXX
    flash_cfg_t cfg = {
        .spi_port = SPI_PORT1,
        .cs_pin = GPIO_PIN_28
    };
    if(flash->open(&cfg)) {
#endif

        printf("error: flash open failed\n");
        return;
    }

    uint8_t rdata[BUF_LEN] = {0};
    uint8_t wdata[BUF_LEN] = {0};

    memset(wdata, 'X', BUF_LEN - 1);

    printf("try to read flash data...\n");

    if(flash->read((uint32_t)flash_test_start_addr, rdata, BUF_LEN)) {
        printf("error: flash read failed\n");
        goto end;
    }

    rdata[strlen(wdata)] = '\0';
    if(strcmp(rdata, wdata)) {
        printf("read nothing\n");
        printf("first running this sample\n");
        printf("writing data: %s\n", wdata);

        if(flash->write((uint32_t)flash_test_start_addr, wdata, strlen(wdata) + 1)) {
            printf("error: flash write failed\n");
            goto end;
        }

        if(flash->read((uint32_t)flash_test_start_addr, rdata, BUF_LEN)) {
            printf("error: flash read failed\n");
            goto end;
        }
    }

    printf("read data: %s\n", rdata);

end:
    flash->close();
}

#if FLASH_TEST == FLASH_TEST_ONCHIP
dev_export(DEV_CLASS_FLASH, CONFIG_FLASH_ONCHIP_NAME, FLASH_TYPE_ONCHIP);
#elif FLASH_TEST == FLASH_TEST_W25QXX
dev_export(DEV_CLASS_GPIO, "gpio_pin_28", GPIO_PIN_28);
dev_export(DEV_CLASS_SPI, "spi1", SPI_PORT1);
dev_export(DEV_CLASS_FLASH, CONFIG_FLASH_W25QXX_NAME, FLASH_TYPE_W25QXX);
#endif
app_export(flash_test, NULL, "flash_test", 16384, 30, 1);
